﻿using HedgehogTeam.EasyTouch;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HighLevelEventHandle : MonoBehaviour
{
    private Camera _camera;
    private Vector3 _moveDir;
    public float moveFactor = 1.2f;
    private float _camera2floorLen;
    // Start is called before the first frame update
    void Start()
    {
        _camera = Camera.main;
        _maxFieldOfView = _camera.fieldOfView;
        //照相机，射到地面 的距离（可以改成射线的方法获取，但是要依赖Boxcollider）
        _camera2floorLen = _camera.transform.position.y * Mathf.Sign(45 * Mathf.Deg2Rad);
    }


    private void OnEnable()
    {
        EasyTouch.On_DragStart += OnDragStart;
        EasyTouch.On_Drag += OnDrag;
        EasyTouch.On_DragEnd += OnDragEnd;
        EasyTouch.On_Pinch += OnPinch;
        Facade.Instance.RegistEvent(GameEvent.UserInput.MoveUnit, OnHandeMoveUnit);
    }

    private void OnDisable()
    {
        EasyTouch.On_DragStart -= OnDragStart;
        EasyTouch.On_Drag -= OnDrag;
        EasyTouch.On_DragEnd -= OnDragEnd;
        EasyTouch.On_Pinch -= OnPinch;
        Facade.Instance.UnRegistEvent(GameEvent.UserInput.MoveUnit, OnHandeMoveUnit);
    }

    private bool _isCanDrag;
    private bool _isMovingUnit;//正在移动Unit
    public void OnDragStart(Gesture gesture)
    {
        if (_isMovingUnit)
            return;
        //Debug.Log("Drag start");
        if(gesture.touchCount > 1)
        {
            _isCanDrag = false;
        }
        else
        {
            _isCanDrag = true;
        }
    }

    private Transform _cameraTrans
    {
        get { return _camera.transform.parent; }
    }
 
    public void OnDrag(Gesture gesture){
        //Debug.Log("Drag delta:" + gesture.deltaPosition);
        if (!_isCanDrag)
            return;

        //记录移动的距离 -号是因为我们要移动的是因为相机来显示物体的移动
        //如果自己移动物体可以不加上-，原理是一样的，直接移动物体会造成重构，特别的有大量物体（比如地图的时候就会出现这种情况），性能上会消耗巨大
        _moveDir = -gesture.deltaPosition;
        //规整z轴方向
        _moveDir = new Vector3(_moveDir.x, 0, _moveDir.y);

        //如果移动的距离为0那么说明没有进行拖拽，直接返回
        if (_moveDir == Vector3.zero)
        {
            return;
        }

        float height, width;
        GetHeightAndWidthOnFloor(out height, out width);
        //计算实际上相机需要移动的距离
        _moveDir.x = _moveDir.x / Screen.width * width;
        _moveDir.z = _moveDir.z / Screen.height * height;

        //相机移动距离:moveDir后面乘上的是一个下面我们要说的一个缩放系数，如果不加上的话会导致缩小之后移动比较慢一点，放大之后移动比较快速
        var delta = _moveDir * moveFactor;
        // Debug.Log("move delta:" + delta);
        _cameraTrans.Translate(delta, Space.World);

        if (IsOutOfBorder(width))
        {
            _cameraTrans.Translate(-delta, Space.World);//todo 学生作业：平滑恢复 参考ClampFieldOfView2Min函数
        }
    }

    private void GetHeightAndWidthOnFloor(out float height, out float width)
    {
        //这一段可以参考 https://www.jianshu.com/p/148725feecfa
        //主要用于做到屏幕移动距离和相机移动距离保持一致，不随着缩放而改变
        float aspect = _camera.aspect;
        float halfFOVTan = Mathf.Tan((_camera.fieldOfView * 0.5f) * Mathf.Deg2Rad);
        //
         height = /*Mathf.Abs(_camera.transform.position.z)*/ _camera2floorLen * halfFOVTan * 2;// 参照图片（计算透视相机视口宽高示意图）
         width = height * aspect;
    }

    private bool IsOutOfBorder(float width)
    {
        var verticalAdd = _cameraTrans.position.y * Mathf.Tan((45 - _camera.fieldOfView * 0.5f) * Mathf.Deg2Rad);
        var verticalAdd1 = _cameraTrans.position.y * Mathf.Tan((45 + _camera.fieldOfView * 0.5f) * Mathf.Deg2Rad);
        if (_cameraTrans.position.x - width < 0)
        {
            Debug.Log("越界X 左边");
            return true;
        }
        if (_cameraTrans.position.x + width > MapMgr.Instance.Horizon)
        {
            Debug.Log("越界X 右边");
            return true;
        }
        else if (_cameraTrans.position.z + verticalAdd < 0)
        {
            Debug.Log("越界Y 下边");
            return true;
        }
        else if (_cameraTrans.position.z + verticalAdd1 > MapMgr.Instance.Vertical)
        {
            Debug.Log("越界Y 上边");
            return true;
        }
        return false;
    }

    public void OnDragEnd(Gesture gesture)
    {
       // Debug.Log("Drag end");
    }


    ////////////////////////////////滚动事件
    private float _minFieldOfView = 1;
    private float _maxFieldOfView = 60;
    private Coroutine _coMinFieldOfView;
    private Coroutine _coMaxFieldOfView;
    public void OnPinch(Gesture gesture)
    {
        // Debug.Log("OnPinch:" + gesture.twoFingerDistance);

        PinchWithDelta(gesture.deltaPinch * 0.2f);
 
    }

    private void OnHandeMoveUnit(object sender)
    {
        _isMovingUnit = (bool)sender;
        _isCanDrag = false;//双重保护
    }
    public void PinchWithDelta(float delta)
    {
        _camera.fieldOfView -= delta;

        float height, width;
        GetHeightAndWidthOnFloor(out height, out width);
        if (IsOutOfBorder(width))
        {
            _camera.fieldOfView += delta;//todo 学生作业：平滑恢复 参考ClampFieldOfView2Min函数
            return;
        }

        //越界处理
        if (_camera.fieldOfView < _minFieldOfView)
        {
            if (_coMinFieldOfView != null)
                StopCoroutine(_coMinFieldOfView);
            _coMinFieldOfView = StartCoroutine(ClampFieldOfView2Min(_minFieldOfView));
        }
        else if (_camera.fieldOfView > _maxFieldOfView)
        {
            if (_coMaxFieldOfView != null)
                StopCoroutine(_coMaxFieldOfView);
            _coMaxFieldOfView = StartCoroutine(ClampFieldOfView2Max(_maxFieldOfView));
        }
    }
    private IEnumerator ClampFieldOfView2Min(float value)
    {
        float oldValue = _camera.fieldOfView;
        for (float i = 0; i < 0.5f; i += Time.deltaTime)
        {
            _camera.fieldOfView = Mathf.Lerp(oldValue, value, i/0.5f);
            yield return null;
        }
        _coMinFieldOfView = null;
    }

    private IEnumerator ClampFieldOfView2Max(float value)
    {
        float oldValue = _camera.fieldOfView;
        for (float i = 0; i < 0.5f; i += Time.deltaTime)
        {
            _camera.fieldOfView = Mathf.Lerp(oldValue, value, i/0.5f);
            yield return null;
        }
        _coMaxFieldOfView = null;
    }


    private void Update()
    {
#if UNITY_EDITOR || UNITY_STANDALONE 
        if(Input.GetAxis("Mouse ScrollWheel") != 0f)
        PinchWithDelta(Input.mouseScrollDelta.y * 0.5f);
#endif
    }
}
